/*     */ package com.zimbra.cs.mailbox.util;
/*     */ 
/*     */ import com.zimbra.common.service.ServiceException;
/*     */ import com.zimbra.common.util.CliUtil;
/*     */ import com.zimbra.common.util.StringUtil;
/*     */ import com.zimbra.cs.db.DbMailItem;
/*     */ import com.zimbra.cs.db.DbPool;
/*     */ import com.zimbra.cs.db.DbPool.DbConnection;
/*     */ import com.zimbra.cs.mailbox.Metadata;
/*     */ import com.zimbra.cs.volume.Volume;
/*     */ import com.zimbra.cs.volume.VolumeManager;
/*     */ import java.io.File;
/*     */ import java.io.PrintStream;
/*     */ import java.sql.PreparedStatement;
/*     */ import java.sql.ResultSet;
/*     */ import java.sql.ResultSetMetaData;
/*     */ import java.sql.SQLException;
/*     */ import java.text.DateFormat;
/*     */ import java.text.SimpleDateFormat;
/*     */ import java.util.ArrayList;
/*     */ import java.util.Iterator;
/*     */ import java.util.LinkedHashMap;
/*     */ import java.util.List;
/*     */ import java.util.Map;
/*     */ import java.util.Map.Entry;
/*     */ import java.util.Set;
/*     */ import org.apache.commons.cli.CommandLine;
/*     */ import org.apache.commons.cli.CommandLineParser;
/*     */ import org.apache.commons.cli.GnuParser;
/*     */ import org.apache.commons.cli.Options;
/*     */ import org.apache.commons.cli.ParseException;
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ public final class MetadataDump
/*     */ {
/*     */   private static final String OPT_MAILBOX_ID = "mailboxId";
/*     */   private static final String OPT_ITEM_ID = "itemId";
/*     */   private static final String OPT_DUMPSTER = "dumpster";
/*     */   private static final String OPT_FILE = "file";
/*     */   private static final String OPT_HELP = "h";
/*     */   private static final String OPT_STR = "String";
/*  62 */   private static Options sOptions = new Options();
/*     */   private static final String METADATA_COLUMN = "metadata";
/*     */   
/*  65 */   static { sOptions.addOption("m", "mailboxId", true, "mailbox id or email");
/*  66 */     sOptions.addOption("i", "itemId", true, "item id (required when --mailboxId is used)");
/*  67 */     sOptions.addOption(null, "dumpster", false, "Get data from the dumpster");
/*  68 */     sOptions.addOption("f", "file", true, "Decode metadata value in a file (other options are ignored)");
/*  69 */     sOptions.addOption("s", "String", true, "Decode metadata value from a string (other options are ignored)");
/*  70 */     sOptions.addOption("h", "help", false, "Show help (this output)");
/*     */   }
/*     */   
/*     */   private static void usage(String errmsg) {
/*  74 */     if (errmsg != null) {
/*  75 */       System.err.println(errmsg);
/*     */     }
/*  77 */     System.err.println("Usage: zmmetadump -m <mailbox id/email> -i <item id> [--dumpster]");
/*  78 */     System.err.println("   or: zmmetadump -f <file containing encoded metadata>");
/*  79 */     System.err.println("   or: zmmetadump -s <encoded string>");
/*     */   }
/*     */   
/*     */   private static CommandLine parseArgs(String[] args) {
/*  83 */     CommandLineParser parser = new GnuParser();
/*  84 */     CommandLine cl = null;
/*     */     try {
/*  86 */       cl = parser.parse(sOptions, args);
/*     */     } catch (ParseException pe) {
/*  88 */       usage(pe.getMessage());
/*  89 */       System.exit(1);
/*     */     }
/*  91 */     return cl;
/*     */   }
/*     */   
/*     */   private static class Row
/*     */     implements Iterable<Map.Entry<String, String>>
/*     */   {
/*  97 */     private Map<String, String> mMap = new LinkedHashMap();
/*     */     
/*     */     void addColumn(String colName, String data)
/*     */       throws ServiceException
/*     */     {
/* 102 */       String key = colName.toLowerCase();
/* 103 */       String value = key.equals("metadata") ? DbMailItem.decodeMetadata(data) : data;
/* 104 */       this.mMap.put(key, value);
/*     */     }
/*     */     
/*     */     public Iterator<Map.Entry<String, String>> iterator() {
/* 108 */       return this.mMap.entrySet().iterator();
/*     */     }
/*     */     
/*     */     String get(String colName) {
/* 112 */       return (String)this.mMap.get(colName.toLowerCase());
/*     */     }
/*     */     
/*     */     void print(PrintStream ps) throws ServiceException {
/* 116 */       ps.println("[Database Columns]");
/* 117 */       for (Map.Entry<String, String> entry : this) {
/* 118 */         String col = (String)entry.getKey();
/* 119 */         if (!col.equalsIgnoreCase("metadata")) {
/* 120 */           String val = (String)entry.getValue();
/* 121 */           if (((col.equalsIgnoreCase("date")) || (col.equalsIgnoreCase("change_date"))) && 
/* 122 */             (val != null)) {
/* 123 */             long t = Long.parseLong(val) * 1000L;
/* 124 */             val = val + " (" + MetadataDump.getTimestampStr(t) + ")";
/*     */           }
/*     */           
/* 127 */           ps.println("  " + col + ": " + (val != null ? val : "<null>"));
/*     */         }
/*     */       }
/* 130 */       ps.println();
/* 131 */       if (this.mMap.get("blob_digest") != null) {
/* 132 */         Volume vol = null;
/*     */         try {
/* 134 */           short volId = Short.parseShort((String)this.mMap.get("locator"));
/* 135 */           vol = VolumeManager.getInstance().getVolume(volId);
/*     */         }
/*     */         catch (NumberFormatException nfe) {}
/*     */         
/* 139 */         if (vol != null) {
/* 140 */           int mboxId = Integer.parseInt((String)this.mMap.get("mailbox_id"));
/* 141 */           String itemIdStr = (String)this.mMap.get("id");
/* 142 */           if (itemIdStr == null)
/* 143 */             itemIdStr = (String)this.mMap.get("item_id");
/* 144 */           int itemId = Integer.parseInt(itemIdStr);
/* 145 */           String dir = vol.getBlobDir(mboxId, itemId);
/* 146 */           String modContent = (String)this.mMap.get("mod_content");
/* 147 */           String blobPath = dir + File.separator + itemIdStr + "-" + modContent + ".msg";
/* 148 */           ps.println("[Blob Path]");
/* 149 */           ps.println(blobPath);
/* 150 */           ps.println();
/*     */         }
/*     */       }
/* 153 */       ps.println("[Metadata]");
/* 154 */       Metadata md = new Metadata((String)this.mMap.get("metadata"));
/* 155 */       ps.println(md.prettyPrint());
/*     */     }
/*     */   }
/*     */   
/*     */   private static int getMailboxGroup(DbPool.DbConnection conn, int mboxId) throws SQLException
/*     */   {
/* 161 */     int gid = 0;
/* 162 */     PreparedStatement stmt = null;
/* 163 */     ResultSet rs = null;
/*     */     try {
/* 165 */       stmt = conn.prepareStatement("SELECT group_id FROM mailbox WHERE id = ?");
/*     */       
/* 167 */       stmt.setInt(1, mboxId);
/* 168 */       rs = stmt.executeQuery();
/* 169 */       if (rs.next())
/* 170 */         gid = rs.getInt(1);
/*     */     } finally {
/* 172 */       if (rs != null)
/* 173 */         rs.close();
/* 174 */       if (stmt != null)
/* 175 */         stmt.close();
/*     */     }
/* 177 */     return gid;
/*     */   }
/*     */   
/*     */   private static int lookupMailboxIdFromEmail(DbPool.DbConnection conn, String email) throws SQLException, ServiceException
/*     */   {
/* 182 */     PreparedStatement stmt = null;
/* 183 */     ResultSet rs = null;
/*     */     try {
/* 185 */       String sql = "SELECT id FROM mailbox WHERE comment=?";
/* 186 */       stmt = conn.prepareStatement(sql);
/* 187 */       stmt.setString(1, email.toUpperCase());
/* 188 */       rs = stmt.executeQuery();
/* 189 */       if (!rs.next())
/* 190 */         throw ServiceException.INVALID_REQUEST("Account " + email + " not found on this host", null);
/* 191 */       return rs.getInt(1);
/*     */     } finally {
/* 193 */       DbPool.closeResults(rs);
/* 194 */       DbPool.closeStatement(stmt);
/*     */     }
/*     */   }
/*     */   
/*     */   private static Row getItemRow(DbPool.DbConnection conn, int groupId, int mboxId, int itemId, boolean fromDumpster) throws ServiceException
/*     */   {
/* 200 */     PreparedStatement stmt = null;
/* 201 */     ResultSet rs = null;
/*     */     try {
/* 203 */       String sql = "SELECT * FROM " + DbMailItem.getMailItemTableName(groupId, fromDumpster) + " WHERE mailbox_id = " + mboxId + " AND id = " + itemId;
/*     */       
/* 205 */       stmt = conn.prepareStatement(sql);
/* 206 */       rs = stmt.executeQuery();
/* 207 */       if (!rs.next()) {
/* 208 */         throw ServiceException.INVALID_REQUEST("No such item: mbox=" + mboxId + ", item=" + itemId, null);
/*     */       }
/*     */       
/* 211 */       Row row = new Row();
/* 212 */       ResultSetMetaData rsMeta = rs.getMetaData();
/* 213 */       int cols = rsMeta.getColumnCount();
/* 214 */       for (int i = 1; i <= cols; i++) {
/* 215 */         String colName = rsMeta.getColumnName(i);
/* 216 */         String colValue = rs.getString(i);
/* 217 */         if (rs.wasNull())
/* 218 */           colValue = null;
/* 219 */         row.addColumn(colName, colValue);
/*     */       }
/* 221 */       return row;
/*     */     } catch (SQLException e) {
/* 223 */       throw ServiceException.INVALID_REQUEST("No such item: mbox=" + mboxId + ", item=" + itemId, e);
/*     */     } finally {
/* 225 */       DbPool.closeResults(rs);
/* 226 */       DbPool.closeStatement(stmt);
/*     */     }
/*     */   }
/*     */   
/*     */   private static List<Row> getRevisionRows(DbPool.DbConnection conn, int groupId, int mboxId, int itemId, boolean fromDumpster) throws ServiceException
/*     */   {
/* 232 */     PreparedStatement stmt = null;
/* 233 */     ResultSet rs = null;
/*     */     try {
/* 235 */       String sql = "SELECT * FROM " + DbMailItem.getRevisionTableName(groupId, fromDumpster) + " WHERE mailbox_id = " + mboxId + " AND item_id = " + itemId + " ORDER BY mailbox_id, item_id, version DESC";
/*     */       
/*     */ 
/* 238 */       stmt = conn.prepareStatement(sql);
/* 239 */       rs = stmt.executeQuery();
/* 240 */       List<Row> rows = new ArrayList();
/* 241 */       Row row; while (rs.next()) {
/* 242 */         row = new Row();
/* 243 */         ResultSetMetaData rsMeta = rs.getMetaData();
/* 244 */         int cols = rsMeta.getColumnCount();
/* 245 */         for (int i = 1; i <= cols; i++) {
/* 246 */           String colName = rsMeta.getColumnName(i);
/* 247 */           String colValue = rs.getString(i);
/* 248 */           if (rs.wasNull())
/* 249 */             colValue = null;
/* 250 */           row.addColumn(colName, colValue);
/*     */         }
/* 252 */         rows.add(row);
/*     */       }
/* 254 */       return rows;
/*     */     } catch (SQLException e) {
/* 256 */       throw ServiceException.INVALID_REQUEST("No such item: mbox=" + mboxId + ", item=" + itemId, e);
/*     */     } finally {
/* 258 */       DbPool.closeResults(rs);
/* 259 */       DbPool.closeStatement(stmt);
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   private static void printBanner(PrintStream out, String title)
/*     */   {
/* 284 */     out.println("********************   " + title + "   ********************");
/*     */   }
/*     */   
/*     */   static String getTimestampStr(long time) {
/* 288 */     DateFormat fmt = new SimpleDateFormat("EEE yyyy/MM/dd HH:mm:ss z");
/* 289 */     return fmt.format(Long.valueOf(time));
/*     */   }
/*     */   
/*     */   public static void doDump(DbPool.DbConnection conn, int mboxId, int itemId, boolean fromDumpster, PrintStream out) throws ServiceException {
/*     */     try {
/* 294 */       int groupId = getMailboxGroup(conn, mboxId);
/*     */       
/* 296 */       first = true;
/*     */       
/* 298 */       Row item = getItemRow(conn, groupId, mboxId, itemId, fromDumpster);
/* 299 */       List<Row> revs = getRevisionRows(conn, groupId, mboxId, itemId, fromDumpster);
/*     */       
/*     */ 
/* 302 */       if (!revs.isEmpty())
/* 303 */         printBanner(out, "Current Revision");
/* 304 */       item.print(out);
/* 305 */       first = false;
/*     */       
/*     */ 
/* 308 */       for (Row rev : revs) {
/* 309 */         String version = rev.get("version");
/* 310 */         if (!first) {
/* 311 */           out.println();
/* 312 */           out.println();
/*     */         }
/* 314 */         printBanner(out, "Revision " + version);
/* 315 */         rev.print(out);
/* 316 */         first = false;
/*     */       }
/*     */     } catch (SQLException e) { boolean first;
/* 319 */       throw ServiceException.FAILURE("error while getting metadata for item " + itemId + " in mailbox " + mboxId, e);
/*     */     }
/*     */   }
/*     */   
/*     */   public static void main(String[] args) {
/*     */     try {
/* 325 */       CliUtil.toolSetup("WARN");
/* 326 */       int mboxId = 0;
/* 327 */       int itemId = 0;
/*     */       
/* 329 */       PrintStream out = new PrintStream(System.out, true, "utf-8");
/*     */       
/* 331 */       CommandLine cl = parseArgs(args);
/* 332 */       if (cl.hasOption("h")) {
/* 333 */         usage(null);
/* 334 */         System.exit(0);
/*     */       }
/*     */       
/*     */ 
/* 338 */       String infileName = cl.getOptionValue("file");
/* 339 */       if (infileName != null) {
/* 340 */         File file = new File(infileName);
/* 341 */         if (file.exists()) {
/* 342 */           String encoded = loadFromFile(file);
/* 343 */           Metadata md = new Metadata(encoded);
/* 344 */           String pretty = md.prettyPrint();
/* 345 */           out.println(pretty);
/* 346 */           return;
/*     */         }
/* 348 */         System.err.println("File " + infileName + " does not exist");
/* 349 */         System.exit(1);
/*     */       }
/*     */       
/*     */ 
/*     */ 
/* 354 */       String encoded = cl.getOptionValue("String");
/* 355 */       if (!StringUtil.isNullOrEmpty(encoded)) {
/* 356 */         Metadata md = new Metadata(encoded);
/* 357 */         String pretty = md.prettyPrint();
/* 358 */         out.println(pretty);
/* 359 */         return;
/*     */       }
/*     */       
/*     */ 
/* 363 */       DbPool.startup();
/* 364 */       DbPool.DbConnection conn = null;
/*     */       try
/*     */       {
/* 367 */         boolean fromDumpster = cl.hasOption("dumpster");
/* 368 */         String mboxIdStr = cl.getOptionValue("mailboxId");
/* 369 */         String itemIdStr = cl.getOptionValue("itemId");
/* 370 */         if ((mboxIdStr == null) || (itemIdStr == null)) {
/* 371 */           usage(null);
/* 372 */           System.exit(1);
/*     */         }
/*     */         else {
/* 375 */           if (mboxIdStr.matches("\\d+")) {
/*     */             try {
/* 377 */               mboxId = Integer.parseInt(mboxIdStr);
/*     */             } catch (NumberFormatException e) {
/* 379 */               System.err.println("Invalid mailbox id " + mboxIdStr);
/* 380 */               System.exit(1);
/*     */             }
/*     */           } else {
/* 383 */             conn = DbPool.getConnection();
/* 384 */             mboxId = lookupMailboxIdFromEmail(conn, mboxIdStr);
/*     */           }
/*     */           try {
/* 387 */             itemId = Integer.parseInt(itemIdStr);
/*     */           } catch (NumberFormatException e) {
/* 389 */             usage(null);
/* 390 */             System.exit(1);
/*     */           }
/*     */           
/* 393 */           if (conn == null)
/* 394 */             conn = DbPool.getConnection();
/* 395 */           doDump(conn, mboxId, itemId, fromDumpster, out);
/*     */         }
/* 397 */       } finally { DbPool.quietClose(conn);
/*     */       }
/*     */     } catch (Exception e) {
/* 400 */       System.err.println(e.getMessage());
/* 401 */       System.err.println();
/* 402 */       System.err.println();
/* 403 */       e.printStackTrace();
/* 404 */       System.exit(1);
/*     */     }
/*     */   }
/*     */   
/*     */   /* Error */
/*     */   private static String loadFromFile(File file)
/*     */     throws ServiceException
/*     */   {
/*     */     // Byte code:
/*     */     //   0: aconst_null
/*     */     //   1: astore_1
/*     */     //   2: new 57	java/io/FileInputStream
/*     */     //   5: dup
/*     */     //   6: aload_0
/*     */     //   7: invokespecial 58	java/io/FileInputStream:<init>	(Ljava/io/File;)V
/*     */     //   10: astore_1
/*     */     //   11: new 59	java/util/Scanner
/*     */     //   14: dup
/*     */     //   15: aload_1
/*     */     //   16: invokespecial 60	java/util/Scanner:<init>	(Ljava/io/InputStream;)V
/*     */     //   19: astore_2
/*     */     //   20: new 26	java/lang/StringBuilder
/*     */     //   23: dup
/*     */     //   24: invokespecial 27	java/lang/StringBuilder:<init>	()V
/*     */     //   27: astore_3
/*     */     //   28: aload_2
/*     */     //   29: invokevirtual 61	java/util/Scanner:hasNextLine	()Z
/*     */     //   32: ifeq +15 -> 47
/*     */     //   35: aload_3
/*     */     //   36: aload_2
/*     */     //   37: invokevirtual 62	java/util/Scanner:nextLine	()Ljava/lang/String;
/*     */     //   40: invokevirtual 29	java/lang/StringBuilder:append	(Ljava/lang/String;)Ljava/lang/StringBuilder;
/*     */     //   43: pop
/*     */     //   44: goto -16 -> 28
/*     */     //   47: aload_3
/*     */     //   48: invokevirtual 31	java/lang/StringBuilder:toString	()Ljava/lang/String;
/*     */     //   51: astore 4
/*     */     //   53: aload_1
/*     */     //   54: ifnull +7 -> 61
/*     */     //   57: aload_1
/*     */     //   58: invokevirtual 63	java/io/FileInputStream:close	()V
/*     */     //   61: aload 4
/*     */     //   63: areturn
/*     */     //   64: astore 5
/*     */     //   66: aload_1
/*     */     //   67: ifnull +7 -> 74
/*     */     //   70: aload_1
/*     */     //   71: invokevirtual 63	java/io/FileInputStream:close	()V
/*     */     //   74: aload 5
/*     */     //   76: athrow
/*     */     //   77: astore_1
/*     */     //   78: new 26	java/lang/StringBuilder
/*     */     //   81: dup
/*     */     //   82: invokespecial 27	java/lang/StringBuilder:<init>	()V
/*     */     //   85: ldc 65
/*     */     //   87: invokevirtual 29	java/lang/StringBuilder:append	(Ljava/lang/String;)Ljava/lang/StringBuilder;
/*     */     //   90: aload_0
/*     */     //   91: invokevirtual 66	java/io/File:getAbsolutePath	()Ljava/lang/String;
/*     */     //   94: invokevirtual 29	java/lang/StringBuilder:append	(Ljava/lang/String;)Ljava/lang/StringBuilder;
/*     */     //   97: invokevirtual 31	java/lang/StringBuilder:toString	()Ljava/lang/String;
/*     */     //   100: aload_1
/*     */     //   101: invokestatic 67	com/zimbra/common/service/ServiceException:FAILURE	(Ljava/lang/String;Ljava/lang/Throwable;)Lcom/zimbra/common/service/ServiceException;
/*     */     //   104: athrow
/*     */     // Line number table:
/*     */     //   Java source line #265	-> byte code offset #0
/*     */     //   Java source line #267	-> byte code offset #2
/*     */     //   Java source line #268	-> byte code offset #11
/*     */     //   Java source line #269	-> byte code offset #20
/*     */     //   Java source line #270	-> byte code offset #28
/*     */     //   Java source line #271	-> byte code offset #35
/*     */     //   Java source line #273	-> byte code offset #47
/*     */     //   Java source line #275	-> byte code offset #53
/*     */     //   Java source line #276	-> byte code offset #57
/*     */     //   Java source line #275	-> byte code offset #64
/*     */     //   Java source line #276	-> byte code offset #70
/*     */     //   Java source line #278	-> byte code offset #77
/*     */     //   Java source line #279	-> byte code offset #78
/*     */     // Local variable table:
/*     */     //   start	length	slot	name	signature
/*     */     //   0	105	0	file	File
/*     */     //   1	70	1	fis	java.io.FileInputStream
/*     */     //   77	24	1	e	java.io.IOException
/*     */     //   19	18	2	scan	java.util.Scanner
/*     */     //   27	21	3	builder	StringBuilder
/*     */     //   64	11	5	localObject	Object
/*     */     // Exception table:
/*     */     //   from	to	target	type
/*     */     //   2	53	64	finally
/*     */     //   64	66	64	finally
/*     */     //   0	61	77	java/io/IOException
/*     */     //   64	77	77	java/io/IOException
/*     */   }
/*     */ }


/* Location:              /home/mint/zimbrastore.jar!/com/zimbra/cs/mailbox/util/MetadataDump.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       0.7.1
 */